home *** CD-ROM | disk | FTP | other *** search
- /* DoScsiCommandWithSense.c */
- /*
- * DoScsiCommandWithSense.c
- * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
- *
- * This is the common entry to the original and asynchronous SCSI Manager calls:
- * if the asynchronous SCSI Manager is present, it calls it. If not present, it
- * calls the original SCSI Manager and executes Request Sense if necessary.
- */
- #include "SCSISimpleSample.h"
-
- void IssueRequestSense(
- register ScsiCmdBlockPtr scsiCmdBlockPtr
- );
-
-
- /*
- * Do one SCSI Command. If the device returns Check Condition, issue Request Sense
- * (original SCSI Manager only) and interpret the sense data. The original SCSI
- * command status is in SCB.status. If it is statusErr or scsiNonZeroStatus,
- * the sense data is in SCB.sense and the Request Sense status is in
- * SCB.requestSenseStatus.
- */
- void
- DoSCSICommandWithSense(
- register ScsiCmdBlockPtr scsiCmdBlockPtr,
- Boolean displayError,
- Boolean enableAsynchSCSI
- )
- {
- unsigned short cmdBlockLength;
-
- #define SCB (*scsiCmdBlockPtr)
-
- /*
- * Store the LUN information in the command block - this is needed
- * for devices that only examine the command block for LUN values.
- * (On SCSI-II, the asynchronous SCSI Manager also includes the
- * LUN in the identify message).
- */
- SCB.command.scsi[1] &= ~0xE0;
- SCB.command.scsi[1] |= (SCB.scsiDevice.LUN & 0x03) << 5;
- cmdBlockLength = SCSIGetCommandLength((Ptr) &SCB.command);
- /*
- * Try to call SCSI Manager 4.3, if it fails with unimpErr, call
- * the old SCSI Manager. Note: AsyncSCSI [in this instance]
- * is synchronous. Real-world applications would use an asynchronous
- * variant.
- */
- if (enableAsynchSCSI == FALSE || gEnableNewSCSIManager == FALSE)
- SCB.status = unimpErr; /* Always original SCSI */
- else {
- SCB.status = AsyncSCSI(
- SCB.scsiDevice, /* Bus/target/LUN */
- &SCB.command, /* The command */
- cmdBlockLength, /* Command length */
- SCB.writeToDevice, /* TRUE if writing */
- SCB.bufferPtr, /* Data buffer, if any */
- SCB.transferSize, /* Data transfer length */
- SCB.transferQuantum, /* 1 means polled */
- &SCB.sense, /* For sense result */
- sizeof SCB.sense, /* Sense buffer size */
- kScsiSpinUpCompletionTime, /* Watchdog timeout */
- &SCB.statusByte, /* Gets STS Phase byte */
- &SCB.messageByte, /* Gets MSG Completion */
- &SCB.actualTransferCount /* Bytes actually done */
- );
- }
- if (SCB.status != unimpErr) {
- /*
- * The asynchronous SCSI Manager did something interesting.
- */
- switch (SCB.status) {
- case noErr:
- break;
- case scsiDeviceNotThere:
- case scsiSelectTimeout:
- case scsiBusInvalid:
- case scsiTIDInvalid:
- /* These all mean "no such device" */
- break;
- case statusErr:
- /*
- * Hmm. If the error is statusErr, the device returned
- * "Check Condition" and the SCSI Manager successfully
- * issued a Request Sense. We'll display the result of the
- * sense and update the spinUpState.
- */
- SCB.requestSenseStatus = noErr;
- if (displayError)
- ShowRequestSense(scsiCmdBlockPtr);
- break;
- default:
- if (displayError)
- ShowStatusError(SCB.scsiDevice, SCB.status, &SCB.command);
- break;
- }
- }
- else {
- /*
- * Call the original SCSI Manager.
- */
- SCB.status = OriginalSCSI(
- SCB.scsiDevice.targetID,
- &SCB.command,
- cmdBlockLength,
- SCB.writeToDevice,
- SCB.bufferPtr,
- SCB.transferSize,
- SCB.transferQuantum,
- kScsiSpinUpCompletionTime,
- &SCB.statusByte,
- &SCB.messageByte,
- &SCB.actualTransferCount
- );
- if (SCB.status != noErr) {
- if (displayError)
- ShowStatusError(SCB.scsiDevice, SCB.status, &SCB.command);
- if (SCB.status == statusErr) {
- /*
- * Device returned "Check Condition."
- */
- IssueRequestSense(scsiCmdBlockPtr);
- if (displayError)
- ShowRequestSense(scsiCmdBlockPtr);
- }
- }
- }
- }
-
- /*
- * Execute "Get Extended Sense." This should not fail. This is only called by
- * "old" SCSI Manager calls: the new SCSI Manager always enables "autosense."
- */
- void
- IssueRequestSense(
- register ScsiCmdBlockPtr scsiCmdBlockPtr
- )
- {
- SCSI_6_Byte_Command requestSense;
- unsigned short statusByte; /* <- From Status Phase */
- unsigned short messageByte; /* <- From Msg Phase */
- unsigned long actualTransferCount;
-
- CLEAR(requestSense);
- requestSense.opcode = kScsiCmdRequestSense;
- requestSense.len = sizeof SCB.sense;
- /*
- * Stuff the logical unit number into the command block.
- */
- requestSense.lbn3 &= 0xE0;
- requestSense.lbn3 |= (SCB.scsiDevice.targetID & 0x03) << 5;
- SCB.requestSenseStatus = OriginalSCSI(
- SCB.scsiDevice.targetID,
- (SCSI_CommandPtr) &requestSense,
- sizeof requestSense,
- FALSE, /* No write */
- (Ptr) &SCB.sense,
- sizeof SCB.sense,
- 1,
- kScsiSpinUpCompletionTime,
- &statusByte,
- &messageByte,
- &actualTransferCount
- );
- }
-
-